﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using SaiLing.Domain;
using SaiLing.Domain.Specification;
using SaiLing.Exceptions;
using SaiLing.Paging;
using SaiLing.SingleSignOn.Application.Service.Interfaces.System;
using SaiLing.SingleSignOn.Domain.Entities.System;
using SaiLing.SingleSignOn.Domain.Interfaces.System;
using SaiLing.SingleSignOn.Domain.Specifications.System;
using System.Linq;

namespace SaiLing.SingleSignOn.Application.Service.Providers.System
{
    public class OrganizationService : BaseService<Organization>,IOrganizationService
    {

        private IModuleActionRepository ModuleActionRepository { get; set; }
        private IModuleRepository ModuleRepository { get; set; }
        private IOrganizationMenuAuthorityRepository OrganizationAuthorityRepository { get; set; }
        private IOrganizationRepository OrganizationRepository { get; set; }

        public OrganizationService(IUnitOfWork unitOfWork, IOrganizationRepository repository, IModuleActionRepository moduleActionRepository, IModuleRepository moduleRepository, IOrganizationMenuAuthorityRepository organizationAuthorityRepository, IOrganizationRepository organizationRepository) : base(unitOfWork, repository)
        {
            ModuleActionRepository = moduleActionRepository;
            ModuleRepository = moduleRepository;
            OrganizationAuthorityRepository = organizationAuthorityRepository;
            OrganizationRepository = organizationRepository;
        }

        public Task<PageData<Organization>> PageList(int pageIndex, int pageSize, string name)
        {
            var spec = new OrganizationSpecification(name);
            return GetMany(spec).ToPageData(pageIndex, pageSize);
        }

        public Task<IEnumerable<Organization>> List(string name)
        {
            var spec = new OrganizationSpecification(name);
            return Task.FromResult(GetMany(spec));
        }

        public async Task<int> Create(Organization entity)
        {
            if (await ExistsAsync(new DirectSpecification<Organization>(x =>x.FullName==entity.FullName)))
                throw new SaiLingException("部门名称重复");
            await Add(entity);
            return await SaveChangesAsync();
        }

        public async Task<int> Edit(Organization entity)
        {
            if (await ExistsAsync(new DirectSpecification<Organization>(x => x.Id != entity.Id && x.FullName == entity.FullName)))
                throw new SaiLingException("部门名称重复");
            Update(entity,
                x => x.FullName,
                x => x.ParentId,
                x => x.ShortName,
                x => x.Sort);
            return await SaveChangesAsync();
        }

        public async Task<int> Delete(Organization[] entityies)
        {
            var ids = entityies.Select(x => x.Id).ToList();
            await LogicRemove(new DirectSpecification<Organization>(x => ids.Contains(x.Id)));
            return await SaveChangesAsync();
        }

        public object GetOrganizationAuthorityObject(Guid? parentOrganizationId = default(Guid?), Guid? organizationId = default(Guid?))
        {
            List<Module> lstModule = new List<Module>();
            object lstActions = null;
            int index = 0;
            IEnumerable<ModuleAction> actioinAll = ModuleActionRepository.GetAll().OrderBy(y => y.Sort);
            if (parentOrganizationId.HasValue && parentOrganizationId != Guid.Empty)
            {
                var parentAuthorities = GetAll().Where(x => !x.LogicRemove && x.Id == parentOrganizationId).FirstOrDefault().OrganizationAuthorities;
                var parentActionIds = parentAuthorities.Select(y => y.ModuleActionId).ToList();
                lstModule = ServiceFactory.GetService<IModuleService>().GetAllModuleByAction(parentActionIds);
                if (organizationId != null)
                {
                    var currentActionIds = GetByKey(organizationId).Result.OrganizationAuthorities.Select(y => y.ModuleActionId).ToList();
                    lstActions = actioinAll.Where(y => parentActionIds.Contains(y.Id)).Select(it => new { ActionId = it.Id, ModuleId = it.ModuleId, it.Name, Checked = currentActionIds.Contains(it.Id), Index = index++ });
                }
                else lstActions = actioinAll.Where(y => parentActionIds.Contains(y.Id)).Select(it => new { ActionId = it.Id, ModuleId = it.ModuleId, it.Name, Checked = false, Index = index++ });
            }
            else
            {
                lstModule = ModuleRepository.GetAll().Where(y => !y.LogicRemove).ToList();
                if (organizationId != null)
                {
                    var currentActionIds = GetByKey(organizationId).Result.OrganizationAuthorities.Select(y => y.ModuleActionId).ToList();
                    //var aa = actioinAll.Where(y => lstModule.Select(z => z.Id).Contains(y.ModuleId)).ToList();
                    lstActions = actioinAll.Where(y => lstModule.Select(z => z.Id).Contains(y.ModuleId)).Select(it => new { ActionId = it.Id, ModuleId = it.ModuleId, it.Name, Index = index++, Checked = currentActionIds.Contains(it.Id) }).ToList();
                }
                else
                    lstActions = actioinAll.Select(it => new { ActionId = it.Id, ModuleId = it.ModuleId, it.Name, Checked = false, Index = index++ });
            }
            return new { modules = lstModule.OrderBy(x => x.ParentId).OrderBy(x => x.Sort).ToTreeList(null, Guid.Empty), actions = lstActions };
        }
    }
}
